home *** CD-ROM | disk | FTP | other *** search
/ CD World Haziran 1997 / CD World Haziran 1997.iso / Cesitlemeler / Directx 3.0 / dx3.exe / SDK / SAMPLES / MISC / D3DAPP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  52.5 KB  |  1,401 lines

  1. /*
  2.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  3.  *
  4.  *  File: d3dapp.c
  5.  *
  6.  *  Top level D3DApp functions and internal global variables.  See
  7.  *  d3dapp.h for more information.
  8.  *
  9.  *  D3DApp is a collection of helper functions for Direct3D applications.
  10.  *  D3DApp consists of the following files:
  11.  *      d3dapp.h    Main D3DApp header to be included by application
  12.  *      d3dappi.h   Internal header
  13.  *      d3dapp.c    D3DApp functions seen by application.
  14.  *      ddcalls.c   All calls to DirectDraw objects except textures
  15.  *      d3dcalls.c  All calls to Direct3D objects except textures
  16.  *      texture.c   Texture loading and managing texture list
  17.  *      misc.c      Miscellaneous calls
  18.  */
  19.  
  20. #include "d3dappi.h"
  21. #include <d3drm.h>  /* For D3DRM error codes only */
  22.  
  23. #define INITGUID
  24.  
  25. /***************************************************************************/
  26. /*                           GLOBAL VARIABLES                              */
  27. /***************************************************************************/
  28. /*
  29.  * All DD and D3D objects which are also available to the application
  30.  * See d3dapp.h for typedef
  31.  */
  32. D3DAppInfo d3dappi;
  33. /*
  34.  * Internal record of the render state.  See d3dapp.h for typedef
  35.  */
  36. D3DAppRenderState d3dapprs; 
  37. /* 
  38.  * Callback functions for D3D device creation and destruction
  39.  */
  40. BOOL(*D3DDeviceDestroyCallback)(LPVOID);
  41. LPVOID D3DDeviceDestroyCallbackContext;
  42. BOOL(*D3DDeviceCreateCallback)(int, int, LPDIRECT3DVIEWPORT*, LPVOID);
  43. LPVOID D3DDeviceCreateCallbackContext;
  44. /*
  45.  * The last error code and string
  46.  */
  47. HRESULT LastError;
  48. char LastErrorString[256];
  49. /*
  50.  * List of dirty rectangles on back buffer and client area
  51.  */
  52. int NumDirtyClientRects, NumDirtyBackRects, NumDirtyZRects;
  53. D3DRECT DirtyClient[D3DAPP_MAXCLEARRECTS];
  54. D3DRECT DirtyBack[D3DAPP_MAXCLEARRECTS];
  55. D3DRECT DirtyZ[D3DAPP_MAXCLEARRECTS];
  56. /*
  57.  * List of texture handles which is copied to D3DAppInfo structure when
  58.  * necessary
  59.  */
  60. D3DTEXTUREHANDLE MasterTextureHandle[D3DAPP_MAXTEXTURES];
  61.  
  62. LPDIRECTDRAWCLIPPER lpClipper; /* Clipper in windowed case */
  63. LPDIRECTDRAWPALETTE lpPalette; /* Front buffer's palette */
  64. PALETTEENTRY ppe[256];         /* Current palette entries */
  65. PALETTEENTRY Originalppe[256]; /* Windows palette entries at startup */
  66. BOOL bD3DAppInitialized;       /* Is D3DApp initialized? */
  67. BOOL bPrimaryPalettized;       /* Is the front buffer palettized? */
  68. BOOL bPaletteActivate;         /* Is the front buffer's palette valid? */
  69. BOOL bIgnoreWM_SIZE;           /* Ignore this WM_SIZE messages */
  70. SIZE szLastClient;             /* Dimensions of the last window */
  71. SIZE szBuffers;                /* Current buffer dimensions, not necessarily
  72.                                   the same as the client window */
  73. int CallbackRefCount;          /* How many times DeviceCreateCallback has
  74.                                   been called in a row */
  75.  
  76. /***************************************************************************/
  77. /*                               FUNCTIONS                                 */
  78. /***************************************************************************/
  79. /*
  80.  * D3DAppCreateFromHWND
  81.  */
  82. BOOL D3DAppCreateFromHWND(DWORD flags, HWND hwnd,
  83.                           BOOL(*DeviceCreateCallback)(int, int,
  84.                                                       LPDIRECT3DVIEWPORT*,
  85.                                                       LPVOID),
  86.                           LPVOID lpCreateContext,
  87.                           BOOL(*DeviceDestroyCallback)(LPVOID),
  88.                           LPVOID lpDestroyContext,
  89.                           D3DAppInfo** D3DApp)
  90. {
  91.     int driver, mode, w, h;
  92.     /* 
  93.      * Clean the global varaibles and check the flags
  94.      */
  95.     D3DAppISetDefaults();
  96.     if (flags & D3DAPP_ONLYSYSTEMMEMORY) {
  97.         d3dappi.bOnlySystemMemory = TRUE;
  98.         d3dappi.bOnlyEmulation = TRUE;
  99.     }
  100.     if (flags & D3DAPP_ONLYD3DEMULATION)
  101.         d3dappi.bOnlyEmulation = TRUE;
  102.     /* 
  103.      * Create DirectDraw, remember the Windows display mode and enumerate the
  104.      * display modes
  105.      */
  106.     ATTEMPT(D3DAppICreateDD(d3dappi.bOnlyEmulation ?
  107.                             D3DAPP_ONLYDDEMULATION : 0L));
  108.     ATTEMPT(D3DAppIRememberWindowsMode());
  109.     ATTEMPT(D3DAppIEnumDisplayModes());
  110.     /*
  111.      * Create Direct3D and enumerate the D3D drivers
  112.      */
  113.     ATTEMPT(D3DAppICreateD3D());
  114.     ATTEMPT(D3DAppIEnumDevices());
  115.     /*
  116.      * Set the device creation and destroy callback functions
  117.      */
  118.     D3DDeviceDestroyCallback = DeviceDestroyCallback;
  119.     D3DDeviceDestroyCallbackContext = lpDestroyContext;
  120.     D3DDeviceCreateCallback = DeviceCreateCallback;
  121.     D3DDeviceCreateCallbackContext = lpCreateContext;
  122.     *D3DApp = &d3dappi;
  123.     d3dappi.hwnd = hwnd;
  124.     /*
  125.      * Choose a driver and display mode.  Using the current window is 
  126.      * prefered, but a fullscreen mode may be selected.  Set the cooperative
  127.      * level and create the front and back buffers for this mode.
  128.      */
  129.     driver = D3DAPP_YOUDECIDE;
  130.     mode = D3DAPP_YOUDECIDE;
  131.     ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
  132.     D3DAppIGetClientWin(hwnd);
  133.     if (mode == D3DAPP_USEWINDOW) {
  134.         w = d3dappi.szClient.cx;
  135.         h = d3dappi.szClient.cy;
  136.         ATTEMPT(D3DAppISetCoopLevel(hwnd, FALSE));
  137.         ATTEMPT(D3DAppICreateBuffers(hwnd, w, h, D3DAPP_BOGUS, FALSE,
  138.                                      d3dappi.Driver[driver].bIsHardware));
  139.         /*
  140.          * Change the currently selected mode if it's not compatible with
  141.          * this driver.  Just to make sure that CurrMode is always a mode the
  142.          * current driver can do.
  143.          */
  144.         if (!(d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth &
  145.               D3DAppIBPPToDDBD(d3dappi.Mode[d3dappi.CurrMode].bpp))){
  146.             ATTEMPT(D3DAppIPickDisplayMode(&d3dappi.CurrMode,
  147.                         d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth));
  148.         }
  149.     } else {
  150.         szLastClient = d3dappi.szClient;
  151.         w = d3dappi.Mode[mode].w;
  152.         h = d3dappi.Mode[mode].h;
  153.         d3dappi.szClient.cx = w; d3dappi.szClient.cy = h;
  154.         ATTEMPT(D3DAppISetCoopLevel(hwnd, TRUE));
  155.         ATTEMPT(D3DAppISetDisplayMode(w, h, d3dappi.Mode[mode].bpp));
  156.         d3dappi.CurrMode = mode;
  157.         ATTEMPT(D3DAppICreateBuffers(hwnd, w, h, d3dappi.Mode[mode].bpp, TRUE,
  158.                                      d3dappi.Driver[driver].bIsHardware));
  159.     }
  160.     /*
  161.      * If the front buffer is palettized, initialize its palette
  162.      */
  163.     ATTEMPT(D3DAppICheckForPalettized());
  164.     /*
  165.      * Create the Z-buffer
  166.      */
  167.     ATTEMPT(D3DAppICreateZBuffer(w, h, driver));
  168.     /*
  169.      * Create the D3D device, load the textures, call the device create
  170.      * callback and set a default render state
  171.      */
  172.     ATTEMPT(D3DAppICreateDevice(driver));
  173.     ATTEMPT(D3DAppILoadAllTextures());
  174.     ATTEMPT(D3DAppIFilterDisplayModes(driver));  /* bThisDriverCanDo flags */
  175.     ATTEMPT(D3DAppICallDeviceCreateCallback(w, h));
  176.     ATTEMPT(D3DAppISetRenderState());
  177.     /* 
  178.      * Initialize dirty rectangle information
  179.      */
  180.     D3DAppIValidateDirtyRects();
  181.     /*
  182.      * Ready to render
  183.      */
  184.     bD3DAppInitialized = TRUE;
  185.     d3dappi.bRenderingIsOK = TRUE;
  186.     return TRUE;
  187.  
  188. exit_with_error:
  189.     D3DAppICallDeviceDestroyCallback();
  190.     RELEASE(d3dappi.lpD3DDevice);
  191.     RELEASE(d3dappi.lpZBuffer);
  192.     RELEASE(lpPalette);
  193.     RELEASE(lpClipper);
  194.     RELEASE(d3dappi.lpBackBuffer);
  195.     RELEASE(d3dappi.lpFrontBuffer);
  196.     if (d3dappi.bFullscreen) {
  197.         D3DAppIRestoreDispMode();
  198.         D3DAppISetCoopLevel(hwnd, FALSE);
  199.     }
  200.     RELEASE(d3dappi.lpD3D);
  201.     RELEASE(d3dappi.lpDD);
  202.     return FALSE;
  203. }   
  204.  
  205. /*
  206.  * D3DAppFullscreen
  207.  */
  208. BOOL D3DAppFullscreen(int mode)
  209. {
  210.     int w, h, bpp;
  211.     BOOL b; /* was already in a fullscreen mode? */
  212.  
  213.     d3dappi.bRenderingIsOK = FALSE;
  214.     /* 
  215.      * Make sure this is a valid request, otherwise doctor mode so it will
  216.      * work with this driver.
  217.      */
  218.     ATTEMPT(D3DAppIVerifyDriverAndMode(&d3dappi.CurrDriver, &mode));
  219.     /* 
  220.      * Release everything
  221.      */
  222.     ATTEMPT(D3DAppICallDeviceDestroyCallback());
  223.     if (d3dappi.bFullscreen) {
  224.         ATTEMPT(D3DAppIClearBuffers());
  225.     }
  226.     D3DAppIReleaseAllTextures();
  227.     RELEASE(d3dappi.lpD3DDevice);
  228.     RELEASE(d3dappi.lpZBuffer);
  229.     RELEASE(lpPalette);
  230.     RELEASE(lpClipper);
  231.     RELEASE(d3dappi.lpBackBuffer);
  232.     RELEASE(d3dappi.lpFrontBuffer);
  233.     /*
  234.      * Record information about the current status
  235.      */
  236.     b = d3dappi.bFullscreen;
  237.     w = d3dappi.Mode[mode].w;
  238.     h = d3dappi.Mode[mode].h;
  239.     bpp = d3dappi.Mode[mode].bpp;
  240.     if (!b) {
  241.         /*
  242.          * If this is not a fullscreen mode, we'll need to record the window
  243.          * size for when we return to it.
  244.          */
  245.         szLastClient = d3dappi.szClient;
  246.     }
  247.     /*
  248.      * Set the cooperative level and create front and back buffers
  249.      */
  250.     d3dappi.szClient.cx = w; d3dappi.szClient.cy = h;
  251.     ATTEMPT(D3DAppISetCoopLevel(d3dappi.hwnd, TRUE));
  252.     ATTEMPT(D3DAppISetDisplayMode(w, h, bpp));
  253.     d3dappi.CurrMode = mode;
  254.     ATTEMPT(D3DAppICreateBuffers(d3dappi.hwnd, w, h, bpp, TRUE,
  255.                                  d3dappi.Driver[d3dappi.CurrDriver].bIsHardware));
  256.     /*
  257.      * If the front buffer is palettized, initialize its palette
  258.      */
  259.     ATTEMPT(D3DAppICheckForPalettized());
  260.     /*
  261.      * Create the Z-buffer
  262.      */
  263.     ATTEMPT(D3DAppICreateZBuffer(w, h, d3dappi.CurrDriver));
  264.     /*
  265.      * Create the D3D device, load the textures, call the device create
  266.      * callback and set a default render state
  267.      */
  268.     ATTEMPT(D3DAppICreateDevice(d3dappi.CurrDriver));
  269.     ATTEMPT(D3DAppILoadAllTextures());
  270.     ATTEMPT(D3DAppICallDeviceCreateCallback(w, h));
  271.     ATTEMPT(D3DAppISetRenderState());
  272.     /* 
  273.      * Set current mode and clear dirty rectangle information
  274.      */
  275.     d3dappi.CurrMode = mode;
  276.     D3DAppIValidateDirtyRects();
  277.     d3dappi.bRenderingIsOK = TRUE;
  278.     return TRUE;
  279.  
  280. exit_with_error:
  281.     D3DAppICallDeviceDestroyCallback();
  282.     RELEASE(d3dappi.lpD3DDevice);
  283.     RELEASE(d3dappi.lpZBuffer);
  284.     RELEASE(lpPalette);
  285.     RELEASE(lpClipper);
  286.     RELEASE(d3dappi.lpBackBuffer);
  287.     RELEASE(d3dappi.lpFrontBuffer);
  288.     if (!b) {
  289.         D3DAppIRestoreDispMode();
  290.         D3DAppISetCoopLevel(d3dappi.hwnd, FALSE);
  291.     }
  292.     return FALSE;
  293. }
  294.  
  295. /*
  296.  * D3DAppWindow
  297.  */
  298. BOOL
  299. D3DAppWindow(int w, int h)
  300. {
  301.     BOOL b; /* changing from a fullscreen mode? */
  302.  
  303.     if (!d3dappi.bIsPrimary) {
  304.         D3DAppISetErrorString("It is not possible to create a D3D window with a hardware DirectDraw device.  Check the bIsPrimary flag before calling D3DAppWindow.");
  305.         return FALSE;
  306.     }
  307.     b = d3dappi.bFullscreen;
  308.     /*
  309.      * If asked to set the window size, return it to the last value or use
  310.      * a default value.
  311.      */
  312.     if (w == D3DAPP_YOUDECIDE) {
  313.         w = b ? szLastClient.cx : D3DAPP_DEFAULTWINDOWDIM;
  314.     }
  315.     if (h == D3DAPP_YOUDECIDE) {
  316.         h = b ? szLastClient.cy : D3DAPP_DEFAULTWINDOWDIM;
  317.     }
  318.     /*
  319.      * Release everything
  320.      */
  321.     d3dappi.bRenderingIsOK = FALSE;
  322.     ATTEMPT(D3DAppICallDeviceDestroyCallback());
  323.     if (b) {
  324.         ATTEMPT(D3DAppIClearBuffers());
  325.     }
  326.     D3DAppIReleaseAllTextures();
  327.     RELEASE(d3dappi.lpD3DDevice);
  328.     RELEASE(d3dappi.lpZBuffer);
  329.     RELEASE(lpPalette);
  330.     RELEASE(lpClipper);
  331.     RELEASE(d3dappi.lpBackBuffer);
  332.     RELEASE(d3dappi.lpFrontBuffer);
  333.     /* 
  334.      * Restore the display mode if we were in a fullscreen mode
  335.      */
  336.     if (b) {
  337.         D3DAppIRestoreDispMode();
  338.     }
  339.     /* 
  340.      * Set the cooperative level and create front and back buffers
  341.      */
  342.     D3DAppISetCoopLevel(d3dappi.hwnd, FALSE);
  343.     D3DAppISetClientSize(d3dappi.hwnd, w, h, b);
  344.     ATTEMPT(D3DAppICreateBuffers(d3dappi.hwnd, w, h, D3DAPP_BOGUS, FALSE,
  345.                                  d3dappi.Driver[d3dappi.CurrDriver].bIsHardware));
  346.     /*
  347.      * If the front buffer is palettized, initialize its palette
  348.      */
  349.     ATTEMPT(D3DAppICheckForPalettized());
  350.     /*
  351.      * Create the Z-buffer
  352.      */
  353.     ATTEMPT(D3DAppICreateZBuffer(szBuffers.cx, szBuffers.cy,
  354.                                  d3dappi.CurrDriver));
  355.     /*
  356.      * Create the D3D device, load the textures, call the device create
  357.      * callback and set a default render state
  358.      */
  359.     ATTEMPT(D3DAppICreateDevice(d3dappi.CurrDriver));
  360.     ATTEMPT(D3DAppILoadAllTextures());          
  361.     ATTEMPT(D3DAppICallDeviceCreateCallback(szBuffers.cx, szBuffers.cy));
  362.     ATTEMPT(D3DAppISetRenderState());
  363.     /* 
  364.      * Clear dirty rectangle information
  365.      */
  366.     D3DAppIValidateDirtyRects();
  367.     d3dappi.bRenderingIsOK = TRUE;
  368.     return TRUE;
  369.  
  370. exit_with_error:
  371.     D3DAppICallDeviceDestroyCallback();
  372.     RELEASE(d3dappi.lpD3DDevice);
  373.     RELEASE(d3dappi.lpZBuffer);
  374.     RELEASE(lpPalette);
  375.     RELEASE(lpClipper);
  376.     RELEASE(d3dappi.lpBackBuffer);
  377.     RELEASE(d3dappi.lpFrontBuffer);
  378.     return FALSE;  
  379. }
  380.  
  381.  
  382. /*
  383.  * D3DAppChangeDriver 
  384.  */
  385. BOOL
  386. D3DAppChangeDriver(int driver, DWORD flags)
  387. {
  388.     int mode;
  389.  
  390.     /*
  391.      * Verify the compatibility of this mode with the specified driver.
  392.      * The mode may change.
  393.      */
  394.     if (d3dappi.bFullscreen)
  395.         mode = d3dappi.CurrMode;
  396.     else
  397.         mode = D3DAPP_USEWINDOW;
  398.     ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
  399.     if (driver == D3DAPP_BOGUS || mode == D3DAPP_BOGUS)
  400.         goto exit_with_error;
  401.     /*
  402.      * Update the current driver and set bThisDriverCanDo flags
  403.      */
  404.     d3dappi.CurrDriver = driver;
  405.     ATTEMPT(D3DAppIFilterDisplayModes(driver));
  406.     /*
  407.      * Either call D3DAppWindow or D3DAppFullscreen depending on mode
  408.      */
  409.     if (mode == D3DAPP_USEWINDOW) {
  410.         if (d3dappi.bFullscreen) {
  411.             /*
  412.              * We need to switch to a window.  D3DApp will either use the
  413.              * size of the last window it saw or use a default size.
  414.              */
  415.             ATTEMPT(D3DAppWindow(D3DAPP_YOUDECIDE, D3DAPP_YOUDECIDE));
  416.         } else {
  417.             /*
  418.              * We need to recreate the current window.  Don't let D3DApp
  419.              * decide on the size.
  420.              */
  421.             ATTEMPT(D3DAppWindow(d3dappi.szClient.cx, d3dappi.szClient.cy));
  422.         }
  423.         /*
  424.          * Change the currently selected mode if it's not compatible with
  425.          * this driver.  Just to make sure that CurrMode is always a mode the
  426.          * current driver can do.
  427.          */
  428.         if (!(d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth &
  429.               D3DAppIBPPToDDBD(d3dappi.Mode[d3dappi.CurrMode].bpp))){
  430.             ATTEMPT(D3DAppIPickDisplayMode(&d3dappi.CurrMode,
  431.                         d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth));
  432.         }
  433.         return TRUE;
  434.     } else {
  435.         /*
  436.          * We need to switch to fullscreen or switch fullscreen modes or stay
  437.          * in the same fullscreen mode.  In any of these cases, we call the
  438.          * same function.
  439.          */
  440.         ATTEMPT(D3DAppFullscreen(mode));
  441.         return TRUE;
  442.     }
  443.  
  444. exit_with_error:
  445.     /*
  446.      * The failed mode setting call would have released everything
  447.      */
  448.     return FALSE;
  449. }
  450.  
  451.  
  452. /*
  453.  * D3DAppWindowProc
  454.  */
  455. BOOL
  456. D3DAppWindowProc(BOOL* bStopProcessing, LRESULT* lresult, HWND hwnd,
  457.                  UINT message, WPARAM wParam, LPARAM lParam)
  458. {
  459.     PAINTSTRUCT ps;
  460.     *bStopProcessing = FALSE;
  461.     if (!bD3DAppInitialized)
  462.         return TRUE;
  463.     /*
  464.      * Look for messages which effect rendering.  In some cases, we will not
  465.      * want the app to continue processing the message, so set the flag and
  466.      * provide a return value in lresult.
  467.      */
  468.     switch(message) {
  469.         case WM_SIZE:
  470.             if (!bIgnoreWM_SIZE) {
  471.                 /*
  472.                  * Too long to fit here, see ddcalls.c. Updates the buffers
  473.                  * and re-creates the device.
  474.                  */
  475.                 ATTEMPT(D3DAppIHandleWM_SIZE(lresult, d3dappi.hwnd, message,
  476.                                              wParam, lParam));
  477.                 *bStopProcessing = TRUE;
  478.             }
  479.             break;
  480.         case WM_MOVE:
  481.             /*
  482.              * Update client window position information
  483.              */
  484.             d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
  485.             ClientToScreen(hwnd, &d3dappi.pClientOnPrimary);
  486.             break;
  487.         case WM_ACTIVATE:
  488.             /*
  489.              * Set the front buffer's palette
  490.              */
  491.             if (bPaletteActivate && bPrimaryPalettized &&
  492.                 d3dappi.lpFrontBuffer) {
  493.                 d3dappi.lpFrontBuffer->lpVtbl->SetPalette(d3dappi.lpFrontBuffer,
  494.                                                           lpPalette);
  495.             }
  496.             break;
  497.         case WM_ACTIVATEAPP:
  498.             d3dappi.bAppActive = (BOOL)wParam;
  499.             break;
  500.         case WM_SETCURSOR:
  501.             /*
  502.              * Prevent the cursor from being shown in fullscreen
  503.              */
  504.             if (d3dappi.bFullscreen && !d3dappi.bPaused) {
  505.                 SetCursor(NULL);
  506.                 *lresult = 1;
  507.                 *bStopProcessing = TRUE;
  508.                 return TRUE;
  509.             }
  510.             break;
  511.         case WM_MOVING:
  512.             /*
  513.              * Prevent the window from moving in fullscreen
  514.              */
  515.             if (d3dappi.bFullscreen) {
  516.                 GetWindowRect(hwnd, (LPRECT)lParam);
  517.                 *lresult = 1;
  518.                 *bStopProcessing = TRUE;
  519.                 return TRUE;
  520.             }
  521.             break;
  522.         case WM_GETMINMAXINFO:
  523.             /*
  524.              * Ensure the window won't resize in fullscreen
  525.              */
  526.             if (d3dappi.bFullscreen) {
  527.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x= d3dappi.ThisMode.w;
  528.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y= d3dappi.ThisMode.h;
  529.                 ((LPMINMAXINFO)lParam)->ptMinTrackSize.x= d3dappi.ThisMode.w;
  530.                 ((LPMINMAXINFO)lParam)->ptMinTrackSize.y= d3dappi.ThisMode.h;
  531.                 *lresult = 0;
  532.                 *bStopProcessing = TRUE;
  533.                 return TRUE;
  534.             } else {
  535.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x =
  536.                                                     d3dappi.WindowsDisplay.w;
  537.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y =
  538.                                                     d3dappi.WindowsDisplay.h;
  539.                 *lresult = 0;
  540.                 *bStopProcessing = TRUE;
  541.                 return TRUE;
  542.             }
  543.             break;
  544.         case WM_PAINT:
  545.             /*
  546.              * Clear the rectangle and blt the backbuffer image
  547.              */
  548.             BeginPaint(hwnd, &ps);
  549.             if (d3dappi.bRenderingIsOK && !d3dappi.bFullscreen) {
  550.                 D3DAppShowBackBuffer(D3DAPP_SHOWALL);
  551.             }
  552.             D3DAppIValidateDirtyRects();
  553.             EndPaint(hwnd, &ps);
  554.             *lresult = 1;
  555.             *bStopProcessing = TRUE;
  556.             return TRUE;
  557.         case WM_NCPAINT:
  558.             /*
  559.              * When in fullscreen mode, don't draw the window frame.
  560.              */
  561.             if (d3dappi.bFullscreen && !d3dappi.bPaused) {
  562.                 *lresult = 0;
  563.                 *bStopProcessing = TRUE;
  564.                 return TRUE;
  565.             }
  566.             break;
  567.     }
  568.     return TRUE;
  569.  
  570. exit_with_error:
  571.     return FALSE;
  572. }
  573.  
  574. /*
  575.  * D3DAppAddTexture 
  576.  */
  577. BOOL
  578. D3DAppAddTexture(const char* imagefile)
  579. {
  580.     if (d3dappi.NumTextures == D3DAPP_MAXTEXTURES - 1) {
  581.         D3DAppISetErrorString("Can only load %i textures.", D3DAPP_MAXTEXTURES);
  582.         return FALSE;
  583.     }
  584.     lstrcpy(d3dappi.ImageFile[d3dappi.NumTextures], imagefile);
  585.     /*
  586.      * If this driver does texture mapping, load the texture.
  587.      * This test also tests that a device has been created.
  588.      */
  589.     if (d3dappi.ThisDriver.bDoesTextures && d3dappi.NumUsableTextures == d3dappi.NumTextures) {
  590.         BOOL bInVideo;
  591.         ATTEMPT(D3DAppILoadTextureSurf(d3dappi.NumTextures, &bInVideo));
  592.         if (!bInVideo && d3dappi.ThisDriver.bIsHardware) {
  593.             D3DAppIReleaseTexture(d3dappi.NumTextures);
  594.         } else {
  595.             ATTEMPT(D3DAppIGetTextureHandle(d3dappi.NumTextures));
  596.             ++d3dappi.NumUsableTextures;
  597.         }
  598.     }
  599.     d3dappi.NumTextures++;
  600.     return TRUE;
  601.  
  602. exit_with_error:
  603.     d3dappi.ImageFile[d3dappi.NumTextures][0] = 0;
  604.     return FALSE;
  605. }
  606.  
  607. /*
  608.  * D3DAppChangeTextureFormat
  609.  */
  610. BOOL
  611. D3DAppChangeTextureFormat(int format)
  612. {
  613.     /*
  614.      * Release all the textures, change the format and load them again
  615.      */
  616.     d3dappi.bRenderingIsOK = FALSE;
  617.     D3DAppIReleaseAllTextures();
  618.     d3dappi.CurrTextureFormat = format;
  619.     memcpy(&d3dappi.ThisTextureFormat, &d3dappi.TextureFormat[format],
  620.            sizeof(D3DAppTextureFormat));
  621.     ATTEMPT(D3DAppILoadAllTextures());
  622.     d3dappi.bRenderingIsOK = TRUE;
  623.     return TRUE;
  624.  
  625. exit_with_error:
  626.     D3DAppIReleaseAllTextures();
  627.     return FALSE;
  628. }
  629.  
  630. /*
  631.  * D3DAppDisableTextures
  632.  */
  633. BOOL
  634. D3DAppDisableTextures(BOOL flag)
  635. {
  636.     int i;
  637.     if (flag == d3dappi.bTexturesDisabled)
  638.         return TRUE;
  639.     if (flag) {
  640.         /*
  641.          * Set all the texture handles to 0
  642.          */
  643.         d3dappi.bTexturesDisabled = TRUE;
  644.         for (i = 0; i < d3dappi.NumTextures; i++)
  645.             d3dappi.TextureHandle[i] = 0;
  646.     } else {
  647.         /*
  648.          * Restore the texture handles from the master array
  649.          */
  650.         d3dappi.bTexturesDisabled = FALSE;
  651.         memcpy(d3dappi.TextureHandle, MasterTextureHandle,
  652.                sizeof(D3DTEXTUREHANDLE) * D3DAPP_MAXTEXTURES);
  653.     }
  654.     return TRUE;
  655. }
  656.  
  657. /*
  658.  * D3DAppSwapTextures
  659.  */
  660. BOOL
  661. D3DAppSwapTextures()
  662. {
  663.     int i;
  664.     char tempfile[30];
  665.     LPDIRECT3DTEXTURE lptempTexture;
  666.     LPDIRECTDRAWSURFACE lptempSurface;
  667.     if (d3dappi.bTexturesDisabled || d3dappi.NumTextures == 0) {
  668.         D3DAppISetErrorString("Cannot swap textures which are disable or not loaded.\n");
  669.         goto exit_with_error;
  670.     }
  671.     if (!d3dappi.ThisDriver.bDoesTextures)
  672.         return TRUE;
  673.     /*
  674.      * Swap texture 1 with 2, then 2 with 3, then 3 with 4, etc.
  675.      * Don't forget the image file names, texture objects and surfaces
  676.      */
  677.     for (i = 0; i < d3dappi.NumUsableTextures - 1; i++) {
  678.         lstrcpy(tempfile, d3dappi.ImageFile[i]);
  679.         lstrcpy(d3dappi.ImageFile[i], d3dappi.ImageFile[i+1]);
  680.         lstrcpy(d3dappi.ImageFile[i+1], tempfile);
  681.         d3dappi.lpD3DDevice->lpVtbl->SwapTextureHandles(d3dappi.lpD3DDevice,
  682.                                                       d3dappi.lpTexture[i],
  683.                                                       d3dappi.lpTexture[i+1]);
  684.         lptempTexture = d3dappi.lpTexture[i];
  685.         d3dappi.lpTexture[i] = d3dappi.lpTexture[i+1];
  686.         d3dappi.lpTexture[i+1] = lptempTexture;
  687.         lptempSurface = d3dappi.lpTextureSurf[i];
  688.         d3dappi.lpTextureSurf[i] = d3dappi.lpTextureSurf[i+1];
  689.         d3dappi.lpTextureSurf[i+1] = lptempSurface;
  690.     }
  691.     return TRUE;
  692. exit_with_error:
  693.     return FALSE;
  694. }
  695.  
  696. /*
  697.  * D3DAppSetRenderState
  698.  */
  699. BOOL
  700. D3DAppSetRenderState(D3DAppRenderState* lpState)
  701. {
  702.     /*
  703.      * If none was provided, reset the current render state.
  704.      */
  705.     if (!lpState)
  706.         lpState = &d3dapprs;
  707.     /*
  708.      * Record this render state and set it.
  709.      */
  710.     if (lpState != &d3dapprs)
  711.         memcpy(&d3dapprs, lpState, sizeof(D3DAppRenderState));
  712.     if (d3dappi.bRenderingIsOK) {
  713.         ATTEMPT(D3DAppISetRenderState());
  714.     }
  715.     return TRUE;
  716.  
  717. exit_with_error:
  718.     return FALSE;
  719. }
  720.  
  721. /*
  722.  * D3DAppGetRenderState
  723.  */
  724. BOOL
  725. D3DAppGetRenderState(D3DAppRenderState* lpState)
  726. {
  727.     memcpy(lpState, &d3dapprs, sizeof(D3DAppRenderState));
  728.     return TRUE;
  729. }
  730.  
  731. /*
  732.  * D3DAppShowBackBuffer
  733.  */
  734. BOOL
  735. D3DAppShowBackBuffer(DWORD flags)
  736. {
  737.     if (!d3dappi.bRenderingIsOK) {
  738.         D3DAppISetErrorString("Cannot call D3DAppShowBackBuffer while bRenderingIsOK is FALSE.\n");
  739.         return FALSE;
  740.     }
  741.     if (d3dappi.bPaused)
  742.         return TRUE;
  743.     if (d3dappi.bFullscreen) {  
  744.         int numtemp;
  745.         D3DRECT temp[D3DAPP_MAXCLEARRECTS];
  746.         /*
  747.          * Flip the back and front buffers
  748.          */
  749.         LastError = d3dappi.lpFrontBuffer->lpVtbl->Flip(d3dappi.lpFrontBuffer,
  750.                                                         d3dappi.lpBackBuffer,
  751.                                                         1);
  752.         if (LastError == DDERR_SURFACELOST) {
  753.             d3dappi.lpFrontBuffer->lpVtbl->Restore(d3dappi.lpFrontBuffer);
  754.             d3dappi.lpBackBuffer->lpVtbl->Restore(d3dappi.lpBackBuffer);
  755.             D3DAppIClearBuffers();
  756.         } else if (LastError != DD_OK) {
  757.             D3DAppISetErrorString("Flipping complex display surface failed.\n%s", D3DAppErrorToString(LastError));
  758.             return FALSE;
  759.         }
  760.         if (d3dappi.bBackBufferInVideo) {
  761.             /*
  762.              * This is a real flip, so the client and back buffer dirty
  763.              * rectangles also flip
  764.              */
  765.             D3DAppICopyRectList(&numtemp, temp, NumDirtyClientRects,
  766.                                 DirtyClient);
  767.             D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
  768.                                 NumDirtyBackRects, DirtyBack);
  769.             D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, numtemp, temp);
  770.         } else {
  771.             /*
  772.              * The flip is being emulated as a blt from a system memory back
  773.              * buffer, so the back buffer's dirty rectangles are now also the
  774.              * client's.
  775.              */
  776.             D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
  777.                                 NumDirtyBackRects, DirtyBack);
  778.         }
  779.     } else {
  780.         int NumFrontRects, NumBufferRects, i;
  781.         RECT front[D3DAPP_MAXCLEARRECTS];
  782.         RECT buffer[D3DAPP_MAXCLEARRECTS];
  783.         /*
  784.          * Set the rectangle to blt from the back to front bufer
  785.          */
  786.         if (flags & D3DAPP_SHOWALL) {
  787.             /*
  788.              * Set to entire client window
  789.              */
  790.             NumBufferRects = 1;
  791.             SetRect(&buffer[0], 0, 0, d3dappi.szClient.cx,
  792.                     d3dappi.szClient.cy);
  793.             SetRect(&front[0],
  794.                     d3dappi.pClientOnPrimary.x, d3dappi.pClientOnPrimary.y,
  795.                     d3dappi.szClient.cx + d3dappi.pClientOnPrimary.x,
  796.                     d3dappi.szClient.cy + d3dappi.pClientOnPrimary.y);
  797.         } else {
  798.             /*
  799.              * Merge the back and front buffer dirty rectangle lists to get
  800.              * a list of rectangles to blt.  This will simultaneously clear
  801.              * the smallest front buffer region while blt'ing all the back
  802.              * buffer which changed.
  803.              */
  804.             D3DAppIMergeRectLists(&NumBufferRects, (LPD3DRECT)buffer,
  805.                                   NumDirtyClientRects, DirtyClient,
  806.                                   NumDirtyBackRects, DirtyBack);
  807.             D3DAppICopyRectList(&NumFrontRects, (LPD3DRECT)front,
  808.                                 NumBufferRects, (LPD3DRECT)buffer);
  809.             for (i = 0; i < NumFrontRects; i++) {
  810.                 front[i].top += d3dappi.pClientOnPrimary.y;
  811.                 front[i].left += d3dappi.pClientOnPrimary.x;
  812.                 front[i].bottom += d3dappi.pClientOnPrimary.y;
  813.                 front[i].right += d3dappi.pClientOnPrimary.x;
  814.             }
  815.         }
  816.         /*
  817.          * Blt the list of rectangles from the back to front buffer
  818.          */
  819.         for (i = 0; i < NumBufferRects; i++) {
  820.             LastError =
  821.                     d3dappi.lpFrontBuffer->lpVtbl->Blt(d3dappi.lpFrontBuffer,
  822.                                              &front[i], d3dappi.lpBackBuffer,
  823.                                              &buffer[i], DDBLT_WAIT, NULL);
  824.             if (LastError == DDERR_SURFACELOST) {
  825.                 d3dappi.lpFrontBuffer->lpVtbl->Restore(d3dappi.lpFrontBuffer);
  826.                 d3dappi.lpBackBuffer->lpVtbl->Restore(d3dappi.lpBackBuffer);
  827.                 D3DAppIClearBuffers();
  828.             } else if (LastError != DD_OK) {
  829.                 D3DAppISetErrorString("Blt of back buffer to front buffer failed.\n%s", D3DAppErrorToString(LastError));
  830.                 return FALSE;
  831.             }
  832.         }
  833.         /*
  834.          * The back buffer's dirty rectangles are now also the client's
  835.          */
  836.         D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
  837.                             NumDirtyBackRects, DirtyBack);
  838.     }
  839.     return TRUE;
  840. }
  841.  
  842. /*
  843.  * D3DAppRenderExtents
  844.  */
  845. BOOL
  846. D3DAppRenderExtents(DWORD dwCount, LPD3DRECT extent, DWORD flags)
  847. {
  848.     if (dwCount > D3DAPP_MAXCLEARRECTS) {
  849.         D3DAppISetErrorString("The number of clear rectangles exceeded D3DAPP_MAXCLEARRECTS.");
  850.         return FALSE;
  851.     }
  852.     if (flags & D3DAPP_CLEARALL) {
  853.         /*
  854.          * Set the back buffer dirty rectangle to the entire client area
  855.          */
  856.         D3DRECT dummy;
  857.         dummy.x1 = dummy.y1 = 0;
  858.         dummy.x2 = d3dappi.szClient.cx;
  859.         dummy.y2 = d3dappi.szClient.cy;
  860.         D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, 1, &dummy);
  861.         D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient, 1, &dummy);
  862.         D3DAppICopyRectList(&NumDirtyZRects, DirtyZ, 1, &dummy);
  863.     } else {
  864.         /*
  865.          * Set the back and Z buffer dirty rectangle list as specified
  866.          */
  867.         D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, dwCount, extent);
  868.         D3DAppICopyRectList(&NumDirtyZRects, DirtyZ, dwCount, extent);
  869.     }
  870.     return TRUE;
  871. }
  872.  
  873. /*
  874.  * D3DAppClearBackBuffer
  875.  */
  876. BOOL
  877. D3DAppClearBackBuffer(DWORD flags)
  878. {
  879.     if (!d3dappi.bRenderingIsOK) {
  880.         D3DAppISetErrorString("Cannot call D3DAppClearBackBuffer while bRenderingIsOK is FALSE.\n");
  881.         return FALSE;
  882.     }
  883.     if (flags & D3DAPP_CLEARALL) {
  884.         /*
  885.          * Clear the entire back buffer
  886.          */
  887.         int clearflags;
  888.         D3DRECT dummy;
  889.         /*
  890.          * Decided wether to clear just back buffer or also z-buffer
  891.          */
  892.         clearflags = D3DCLEAR_TARGET;
  893.         if (d3dapprs.bZBufferOn)
  894.             clearflags |= D3DCLEAR_ZBUFFER;
  895.         dummy.x1 = dummy.y1 = 0;
  896.         dummy.x2 = d3dappi.szClient.cx;
  897.         dummy.y2 = d3dappi.szClient.cy;
  898.         LastError =
  899.                   d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
  900.                                                        1, &dummy,
  901.                                                        clearflags);
  902.         if (LastError != D3D_OK) {
  903.             D3DAppISetErrorString("Viewport clear failed.\n%s",
  904.                                   D3DAppErrorToString(LastError));
  905.             return FALSE;
  906.         }
  907.     } else {
  908.         /*
  909.          * Clear the dirty rectangles on the back buffer
  910.          */
  911.         LastError =
  912.                   d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
  913.                                                        NumDirtyBackRects,
  914.                                                       DirtyBack, D3DCLEAR_TARGET);
  915.         if (LastError != D3D_OK) {
  916.             D3DAppISetErrorString("Viewport clear of back buffer failed.\n%s",
  917.                                   D3DAppErrorToString(LastError));
  918.             return FALSE;
  919.         }
  920.         /*
  921.          * Clear the dirty rectangles on the Z buffer
  922.          */
  923.         LastError =
  924.                   d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
  925.                                                        NumDirtyZRects,
  926.                                                       DirtyZ, D3DCLEAR_ZBUFFER);
  927.         if (LastError != D3D_OK) {
  928.             D3DAppISetErrorString("Viewport clear of Z buffer failed.\n%s",
  929.                                   D3DAppErrorToString(LastError));
  930.             return FALSE;
  931.         }
  932.  
  933.     }
  934.     return TRUE;
  935. }
  936.  
  937. /*
  938.  * D3DAppCheckForLostSurfaces
  939.  */
  940. #define CHECKSURF(x) if (x) {                                               \
  941.                         if (x->lpVtbl->IsLost(x) == DDERR_SURFACELOST) {    \
  942.                             LastError = x->lpVtbl->Restore(x);              \
  943.                             if (LastError != DD_OK) goto exit_with_error;   \
  944.                             b = TRUE;                                       \
  945.                         }                                                   \
  946.                      }
  947. BOOL
  948. D3DAppCheckForLostSurfaces(void)
  949. {
  950.     int i;
  951.     BOOL b = FALSE;
  952.     /*
  953.      * Check all the surfaces D3DApp owns and restore them if lost.
  954.      */
  955.     CHECKSURF(d3dappi.lpFrontBuffer);
  956.     CHECKSURF(d3dappi.lpBackBuffer);
  957.     CHECKSURF(d3dappi.lpZBuffer);
  958.     if (b) {
  959.         /*
  960.          * If any of the surfaces were lost and restored, clear all the buffers.
  961.          * If this fails, that's fine, just move on.
  962.          */
  963.         D3DAppIClearBuffers();
  964.     }
  965.     for (i = 0; i < d3dappi.NumUsableTextures; i++) {
  966.         b = FALSE;
  967.         CHECKSURF(d3dappi.lpTextureSurf[i]);
  968.         if (b) {
  969.             ATTEMPT(D3DAppIReloadTextureSurf(i));
  970.         }
  971.     }
  972.     return TRUE;
  973.  
  974. exit_with_error:
  975.     D3DAppISetErrorString("Restoring of a lost surface failed.\n%s",
  976.                           D3DAppErrorToString(LastError));
  977.     return FALSE;
  978. }
  979.  
  980. /*
  981.  * D3DAppPause
  982.  */
  983. BOOL
  984. D3DAppPause(BOOL flag)
  985. {
  986.     static int pausecount;
  987.  
  988.     /*
  989.      * Keep a count of the number of times D3DAppPause has been called to 
  990.      * prevent pausing more than once in a row.
  991.      */
  992.     if (pausecount != 0) {
  993.         if (flag) {
  994.             ++pausecount;
  995.             return TRUE;
  996.         } else {
  997.             --pausecount;
  998.             if (pausecount != 0)
  999.                 return TRUE;
  1000.         } 
  1001.     }
  1002.  
  1003.     d3dappi.bPaused = flag;
  1004.     if (!flag) {
  1005.         /*
  1006.          * Returning from a pause
  1007.          */
  1008.         if (d3dappi.bFullscreen && bPrimaryPalettized && lpPalette) {
  1009.             /*
  1010.              * Set front buffer's palette back to what it was before pause
  1011.              */
  1012.             LastError = lpPalette->lpVtbl->SetEntries(lpPalette, 0, 0, 256,
  1013.                                                       &ppe[0]);
  1014.             if (LastError != DD_OK) {
  1015.                 D3DAppISetErrorString("Setting palette entries during unpause failed.\n%s", D3DAppErrorToString(LastError));
  1016.                 goto exit_with_error;
  1017.             }
  1018.         }
  1019.         /*
  1020.          * Dirty rectangle info is no longer valid
  1021.          */
  1022.         D3DAppIValidateDirtyRects();
  1023.     }
  1024.     if (flag && d3dappi.bFullscreen) {
  1025.         /*
  1026.          * Pausing in a fullscreen mode
  1027.          */
  1028.         if (bPrimaryPalettized && lpPalette) {
  1029.             /*
  1030.              * Save the front buffer's current palette and restore the
  1031.              * original Windows palette.
  1032.              */
  1033.             int i;
  1034.             LastError = lpPalette->lpVtbl->GetEntries(lpPalette, 0, 0, 256,
  1035.                                                       &ppe[0]);
  1036.             if (LastError != DD_OK) {
  1037.                 D3DAppISetErrorString("Getting palette entries before a pause failed.\n%s", D3DAppErrorToString(LastError));
  1038.                 goto exit_with_error;
  1039.             }
  1040.             for (i = 10; i < 246; i++)
  1041.                 Originalppe[i] = ppe[i];
  1042.             LastError = lpPalette->lpVtbl->SetEntries(lpPalette, 0, 0, 256,
  1043.                                                       &Originalppe[0]);
  1044.             if (LastError != DD_OK) {
  1045.                 D3DAppISetErrorString("Returning palette entries to defaults failed.\n%s", D3DAppErrorToString(LastError));
  1046.                 goto exit_with_error;
  1047.             }
  1048.         }
  1049.         /*
  1050.          * Flip to GDI surface (either front or back buffer)
  1051.          */
  1052.         if (d3dappi.bIsPrimary && d3dappi.lpDD) {
  1053.             LastError = d3dappi.lpDD->lpVtbl->FlipToGDISurface(d3dappi.lpDD);
  1054.             if (LastError != DD_OK) {
  1055.                 D3DAppISetErrorString("Flipping to GDI surface failed.\n%s", D3DAppErrorToString(LastError));
  1056.                 goto exit_with_error;
  1057.             }
  1058.         }
  1059.         /*
  1060.          * Draw the menu and frame
  1061.          */
  1062.         DrawMenuBar(d3dappi.hwnd);
  1063.         RedrawWindow(d3dappi.hwnd, NULL, NULL, RDW_FRAME);
  1064.     }
  1065.     return TRUE;
  1066. exit_with_error:
  1067.     return FALSE;
  1068. }
  1069.  
  1070. /*
  1071.  * D3DAppCreateSurface
  1072.  */
  1073. BOOL
  1074. D3DAppCreateSurface(DDSURFACEDESC *ddsd, LPDIRECTDRAWSURFACE *lplpSurf)
  1075. {
  1076.     return D3DAppICreateSurface(ddsd, lplpSurf);
  1077. }
  1078.  
  1079. /*
  1080.  * D3DAppLastError
  1081.  */
  1082. HRESULT
  1083. D3DAppLastError(void)
  1084. {
  1085.     return LastError;  
  1086. }
  1087.  
  1088. /*
  1089.  * D3DAppLastD3DAppISetErrorString
  1090.  */
  1091. char*
  1092. D3DAppLastErrorString(void)
  1093. {
  1094.     return LastErrorString;
  1095. }
  1096.  
  1097.  
  1098. /*
  1099.  * D3DAppDestroy
  1100.  */
  1101. BOOL
  1102. D3DAppDestroy(void)
  1103. {
  1104.     /*
  1105.      * Destroys all objects including Direct Draw.
  1106.      */
  1107.     d3dappi.bRenderingIsOK = FALSE;
  1108.     d3dappi.hwnd = NULL;
  1109.     ATTEMPT(D3DAppICallDeviceDestroyCallback());
  1110.     D3DAppIReleaseAllTextures();
  1111.     RELEASE(d3dappi.lpD3DDevice);
  1112.     RELEASE(d3dappi.lpZBuffer);
  1113.     RELEASE(lpPalette);
  1114.     RELEASE(lpClipper);
  1115.     RELEASE(d3dappi.lpBackBuffer);
  1116.     RELEASE(d3dappi.lpFrontBuffer);
  1117.     if (d3dappi.bFullscreen) {
  1118.         D3DAppIRestoreDispMode();
  1119.         D3DAppISetCoopLevel(d3dappi.hwnd, FALSE);
  1120.     }
  1121.     D3DAppIReleasePathList();
  1122.     RELEASE(d3dappi.lpD3D);
  1123.     RELEASE(d3dappi.lpDD);
  1124.     return TRUE;
  1125. exit_with_error:
  1126.     return FALSE;
  1127. }
  1128.  
  1129.  
  1130. /*
  1131.  * D3DAppErrorToString
  1132.  */
  1133. char*
  1134. D3DAppErrorToString(HRESULT error)
  1135. {
  1136.     switch(error) {
  1137.         case DD_OK:
  1138.             return "No error.\0";
  1139.         case DDERR_ALREADYINITIALIZED:
  1140.             return "This object is already initialized.\0";
  1141.         case DDERR_BLTFASTCANTCLIP:
  1142.             return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
  1143.         case DDERR_CANNOTATTACHSURFACE:
  1144.             return "This surface can not be attached to the requested surface.\0";
  1145.         case DDERR_CANNOTDETACHSURFACE:
  1146.             return "This surface can not be detached from the requested surface.\0";
  1147.         case DDERR_CANTCREATEDC:
  1148.             return "Windows can not create any more DCs.\0";
  1149.         case DDERR_CANTDUPLICATE:
  1150.             return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
  1151.         case DDERR_CLIPPERISUSINGHWND:
  1152.             return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
  1153.         case DDERR_COLORKEYNOTSET:
  1154.             return "No src color key specified for this operation.\0";
  1155.         case DDERR_CURRENTLYNOTAVAIL:
  1156.             return "Support is currently not available.\0";
  1157.         case DDERR_DIRECTDRAWALREADYCREATED:
  1158.             return "A DirectDraw object representing this driver has already been created for this process.\0";
  1159.         case DDERR_EXCEPTION:
  1160.             return "An exception was encountered while performing the requested operation.\0";
  1161.         case DDERR_EXCLUSIVEMODEALREADYSET:
  1162.             return "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
  1163.         case DDERR_GENERIC:
  1164.             return "Generic failure.\0";
  1165.         case DDERR_HEIGHTALIGN:
  1166.             return "Height of rectangle provided is not a multiple of reqd alignment.\0";
  1167.         case DDERR_HWNDALREADYSET:
  1168.             return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
  1169.         case DDERR_HWNDSUBCLASSED:
  1170.             return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
  1171.         case DDERR_IMPLICITLYCREATED:
  1172.             return "This surface can not be restored because it is an implicitly created surface.\0";
  1173.         case DDERR_INCOMPATIBLEPRIMARY:
  1174.             return "Unable to match primary surface creation request with existing primary surface.\0";
  1175.         case DDERR_INVALIDCAPS:
  1176.             return "One or more of the caps bits passed to the callback are incorrect.\0";
  1177.         case DDERR_INVALIDCLIPLIST:
  1178.             return "DirectDraw does not support the provided cliplist.\0";
  1179.         case DDERR_INVALIDDIRECTDRAWGUID:
  1180.             return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
  1181.         case DDERR_INVALIDMODE:
  1182.             return "DirectDraw does not support the requested mode.\0";
  1183.         case DDERR_INVALIDOBJECT:
  1184.             return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
  1185.         case DDERR_INVALIDPARAMS:
  1186.             return "One or more of the parameters passed to the function are incorrect.\0";
  1187.         case DDERR_INVALIDPIXELFORMAT:
  1188.             return "The pixel format was invalid as specified.\0";
  1189.         case DDERR_INVALIDPOSITION:
  1190.             return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
  1191.         case DDERR_INVALIDRECT:
  1192.             return "Rectangle provided was invalid.\0";
  1193.         case DDERR_LOCKEDSURFACES:
  1194.             return "Operation could not be carried out because one or more surfaces are locked.\0";
  1195.         case DDERR_NO3D:
  1196.             return "There is no 3D present.\0";
  1197.         case DDERR_NOALPHAHW:
  1198.             return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
  1199.         case DDERR_NOBLTHW:
  1200.             return "No blitter hardware present.\0";
  1201.         case DDERR_NOCLIPLIST:
  1202.             return "No cliplist available.\0";
  1203.         case DDERR_NOCLIPPERATTACHED:
  1204.             return "No clipper object attached to surface object.\0";
  1205.         case DDERR_NOCOLORCONVHW:
  1206.             return "Operation could not be carried out because there is no color conversion hardware present or available.\0";
  1207.         case DDERR_NOCOLORKEY:
  1208.             return "Surface doesn't currently have a color key\0";
  1209.         case DDERR_NOCOLORKEYHW:
  1210.             return "Operation could not be carried out because there is no hardware support of the destination color key.\0";
  1211.         case DDERR_NOCOOPERATIVELEVELSET:
  1212.             return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
  1213.         case DDERR_NODC:
  1214.             return "No DC was ever created for this surface.\0";
  1215.         case DDERR_NODDROPSHW:
  1216.             return "No DirectDraw ROP hardware.\0";
  1217.         case DDERR_NODIRECTDRAWHW:
  1218.             return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
  1219.         case DDERR_NOEMULATION:
  1220.             return "Software emulation not available.\0";
  1221.         case DDERR_NOEXCLUSIVEMODE:
  1222.             return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
  1223.         case DDERR_NOFLIPHW:
  1224.             return "Flipping visible surfaces is not supported.\0";
  1225.         case DDERR_NOGDI:
  1226.             return "There is no GDI present.\0";
  1227.         case DDERR_NOHWND:
  1228.             return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
  1229.         case DDERR_NOMIRRORHW:
  1230.             return "Operation could not be carried out because there is no hardware present or available.\0";
  1231.         case DDERR_NOOVERLAYDEST:
  1232.             return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
  1233.         case DDERR_NOOVERLAYHW:
  1234.             return "Operation could not be carried out because there is no overlay hardware present or available.\0";
  1235.         case DDERR_NOPALETTEATTACHED:
  1236.             return "No palette object attached to this surface.\0";
  1237.         case DDERR_NOPALETTEHW:
  1238.             return "No hardware support for 16 or 256 color palettes.\0";
  1239.         case DDERR_NORASTEROPHW:
  1240.             return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
  1241.         case DDERR_NOROTATIONHW:
  1242.             return "Operation could not be carried out because there is no rotation hardware present or available.\0";
  1243.         case DDERR_NOSTRETCHHW:
  1244.             return "Operation could not be carried out because there is no hardware support for stretching.\0";
  1245.         case DDERR_NOT4BITCOLOR:
  1246.             return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
  1247.         case DDERR_NOT4BITCOLORINDEX:
  1248.             return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
  1249.         case DDERR_NOT8BITCOLOR:
  1250.             return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
  1251.         case DDERR_NOTAOVERLAYSURFACE:
  1252.             return "Returned when an overlay member is called for a non-overlay surface.\0";
  1253.         case DDERR_NOTEXTUREHW:
  1254.             return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
  1255.         case DDERR_NOTFLIPPABLE:
  1256.             return "An attempt has been made to flip a surface that is not flippable.\0";
  1257.         case DDERR_NOTFOUND:
  1258.             return "Requested item was not found.\0";
  1259.         case DDERR_NOTLOCKED:
  1260.             return "Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
  1261.         case DDERR_NOTPALETTIZED:
  1262.             return "The surface being used is not a palette-based surface.\0";
  1263.         case DDERR_NOVSYNCHW:
  1264.             return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
  1265.         case DDERR_NOZBUFFERHW:
  1266.             return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
  1267.         case DDERR_NOZOVERLAYHW:
  1268.             return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
  1269.         case DDERR_OUTOFCAPS:
  1270.             return "The hardware needed for the requested operation has already been allocated.\0";
  1271.         case DDERR_OUTOFMEMORY:
  1272.             return "DirectDraw does not have enough memory to perform the operation.\0";
  1273.         case DDERR_OUTOFVIDEOMEMORY:
  1274.             return "DirectDraw does not have enough memory to perform the operation.\0";
  1275.         case DDERR_OVERLAYCANTCLIP:
  1276.             return "The hardware does not support clipped overlays.\0";
  1277.         case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
  1278.             return "Can only have ony color key active at one time for overlays.\0";
  1279.         case DDERR_OVERLAYNOTVISIBLE:
  1280.             return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
  1281.         case DDERR_PALETTEBUSY:
  1282.             return "Access to this palette is being refused because the palette is already locked by another thread.\0";
  1283.         case DDERR_PRIMARYSURFACEALREADYEXISTS:
  1284.             return "This process already has created a primary surface.\0";
  1285.         case DDERR_REGIONTOOSMALL:
  1286.             return "Region passed to Clipper::GetClipList is too small.\0";
  1287.         case DDERR_SURFACEALREADYATTACHED:
  1288.             return "This surface is already attached to the surface it is being attached to.\0";
  1289.         case DDERR_SURFACEALREADYDEPENDENT:
  1290.             return "This surface is already a dependency of the surface it is being made a dependency of.\0";
  1291.         case DDERR_SURFACEBUSY:
  1292.             return "Access to this surface is being refused because the surface is already locked by another thread.\0";
  1293.         case DDERR_SURFACEISOBSCURED:
  1294.             return "Access to surface refused because the surface is obscured.\0";
  1295.         case DDERR_SURFACELOST:
  1296.             return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
  1297.         case DDERR_SURFACENOTATTACHED:
  1298.             return "The requested surface is not attached.\0";
  1299.         case DDERR_TOOBIGHEIGHT:
  1300.             return "Height requested by DirectDraw is too large.\0";
  1301.         case DDERR_TOOBIGSIZE:
  1302.             return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
  1303.         case DDERR_TOOBIGWIDTH:
  1304.             return "Width requested by DirectDraw is too large.\0";
  1305.         case DDERR_UNSUPPORTED:
  1306.             return "Action not supported.\0";
  1307.         case DDERR_UNSUPPORTEDFORMAT:
  1308.             return "FOURCC format requested is unsupported by DirectDraw.\0";
  1309.         case DDERR_UNSUPPORTEDMASK:
  1310.             return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
  1311.         case DDERR_VERTICALBLANKINPROGRESS:
  1312.             return "Vertical blank is in progress.\0";
  1313.         case DDERR_WASSTILLDRAWING:
  1314.             return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
  1315.         case DDERR_WRONGMODE:
  1316.             return "This surface can not be restored because it was created in a different mode.\0";
  1317.         case DDERR_XALIGN:
  1318.             return "Rectangle provided was not horizontally aligned on required boundary.\0";
  1319.         case D3DERR_BADMAJORVERSION:
  1320.             return "D3DERR_BADMAJORVERSION\0";
  1321.         case D3DERR_BADMINORVERSION:
  1322.             return "D3DERR_BADMINORVERSION\0";
  1323.         case D3DERR_EXECUTE_LOCKED:
  1324.             return "D3DERR_EXECUTE_LOCKED\0";
  1325.         case D3DERR_EXECUTE_NOT_LOCKED:
  1326.             return "D3DERR_EXECUTE_NOT_LOCKED\0";
  1327.         case D3DERR_EXECUTE_CREATE_FAILED:
  1328.             return "D3DERR_EXECUTE_CREATE_FAILED\0";
  1329.         case D3DERR_EXECUTE_DESTROY_FAILED:
  1330.             return "D3DERR_EXECUTE_DESTROY_FAILED\0";
  1331.         case D3DERR_EXECUTE_LOCK_FAILED:
  1332.             return "D3DERR_EXECUTE_LOCK_FAILED\0";
  1333.         case D3DERR_EXECUTE_UNLOCK_FAILED:
  1334.             return "D3DERR_EXECUTE_UNLOCK_FAILED\0";
  1335.         case D3DERR_EXECUTE_FAILED:
  1336.             return "D3DERR_EXECUTE_FAILED\0";
  1337.         case D3DERR_EXECUTE_CLIPPED_FAILED:
  1338.             return "D3DERR_EXECUTE_CLIPPED_FAILED\0";
  1339.         case D3DERR_TEXTURE_NO_SUPPORT:
  1340.             return "D3DERR_TEXTURE_NO_SUPPORT\0";
  1341.         case D3DERR_TEXTURE_NOT_LOCKED:
  1342.             return "D3DERR_TEXTURE_NOT_LOCKED\0";
  1343.         case D3DERR_TEXTURE_LOCKED:
  1344.             return "D3DERR_TEXTURELOCKED\0";
  1345.         case D3DERR_TEXTURE_CREATE_FAILED:
  1346.             return "D3DERR_TEXTURE_CREATE_FAILED\0";
  1347.         case D3DERR_TEXTURE_DESTROY_FAILED:
  1348.             return "D3DERR_TEXTURE_DESTROY_FAILED\0";
  1349.         case D3DERR_TEXTURE_LOCK_FAILED:
  1350.             return "D3DERR_TEXTURE_LOCK_FAILED\0";
  1351.         case D3DERR_TEXTURE_UNLOCK_FAILED:
  1352.             return "D3DERR_TEXTURE_UNLOCK_FAILED\0";
  1353.         case D3DERR_TEXTURE_LOAD_FAILED:
  1354.             return "D3DERR_TEXTURE_LOAD_FAILED\0";
  1355.         case D3DERR_MATRIX_CREATE_FAILED:
  1356.             return "D3DERR_MATRIX_CREATE_FAILED\0";
  1357.         case D3DERR_MATRIX_DESTROY_FAILED:
  1358.             return "D3DERR_MATRIX_DESTROY_FAILED\0";
  1359.         case D3DERR_MATRIX_SETDATA_FAILED:
  1360.             return "D3DERR_MATRIX_SETDATA_FAILED\0";
  1361.         case D3DERR_SETVIEWPORTDATA_FAILED:
  1362.             return "D3DERR_SETVIEWPORTDATA_FAILED\0";
  1363.         case D3DERR_MATERIAL_CREATE_FAILED:
  1364.             return "D3DERR_MATERIAL_CREATE_FAILED\0";
  1365.         case D3DERR_MATERIAL_DESTROY_FAILED:
  1366.             return "D3DERR_MATERIAL_DESTROY_FAILED\0";
  1367.         case D3DERR_MATERIAL_SETDATA_FAILED:
  1368.             return "D3DERR_MATERIAL_SETDATA_FAILED\0";
  1369.         case D3DERR_LIGHT_SET_FAILED:
  1370.             return "D3DERR_LIGHT_SET_FAILED\0";
  1371.         case D3DRMERR_BADOBJECT:
  1372.             return "D3DRMERR_BADOBJECT\0";
  1373.         case D3DRMERR_BADTYPE:
  1374.             return "D3DRMERR_BADTYPE\0";
  1375.         case D3DRMERR_BADALLOC:
  1376.             return "D3DRMERR_BADALLOC\0";
  1377.         case D3DRMERR_FACEUSED:
  1378.             return "D3DRMERR_FACEUSED\0";
  1379.         case D3DRMERR_NOTFOUND:
  1380.             return "D3DRMERR_NOTFOUND\0";
  1381.         case D3DRMERR_NOTDONEYET:
  1382.             return "D3DRMERR_NOTDONEYET\0";
  1383.         case D3DRMERR_FILENOTFOUND:
  1384.             return "The file was not found.\0";
  1385.         case D3DRMERR_BADFILE:
  1386.             return "D3DRMERR_BADFILE\0";
  1387.         case D3DRMERR_BADDEVICE:
  1388.             return "D3DRMERR_BADDEVICE\0";
  1389.         case D3DRMERR_BADVALUE:
  1390.             return "D3DRMERR_BADVALUE\0";
  1391.         case D3DRMERR_BADMAJORVERSION:
  1392.             return "D3DRMERR_BADMAJORVERSION\0";
  1393.         case D3DRMERR_BADMINORVERSION:
  1394.             return "D3DRMERR_BADMINORVERSION\0";
  1395.         case D3DRMERR_UNABLETOEXECUTE:
  1396.             return "D3DRMERR_UNABLETOEXECUTE\0";
  1397.         default:
  1398.             return "Unrecognized error value.\0";
  1399.     }
  1400. }
  1401.